package ru.ifmo.rybakov.muclumon.analysis;

import java.util.HashSet;
import java.util.Set;

import ru.ifmo.rybakov.muclumon.Property;
import ru.ifmo.rybakov.muclumon.PropertyManager;
import ru.ifmo.rybakov.muclumon.Task;


public class TaskPropertiesComparator implements IClusterComparator {

	/* (non-Javadoc)
	 * @see ru.ifmo.rybakov.muclumon.analysis.IClusterManager#getDistance(ru.ifmo.rybakov.muclumon.analysis.ICluster, ru.ifmo.rybakov.muclumon.analysis.ICluster)
	 */
	@Override
	public double getDistance(ICluster first, ICluster second) {
		
		assert (first instanceof TaskCluster) : "Unsupported cluster type";
		assert (second instanceof TaskCluster) : "Unsupported cluster type";
		
		TaskCluster firstTaskCluster = (TaskCluster) first;
		TaskCluster secondTaskCluster = (TaskCluster) second;
		
		Set<Property> firstClusterProperties = getPropertySet(firstTaskCluster);
		Set<Property> secondClusterProperties = getPropertySet(secondTaskCluster);
		
		double distance = 0.0;
		int n = 0;
		for (Property property : firstClusterProperties) {
			if (property.equals(PropertyManager.get("task.application"))) {
				continue;
			}
			if (!secondClusterProperties.contains(property)) {
				distance += Math.pow(1, n);
				n++;
			}
		}
		for (Property property : secondClusterProperties) {
			if (property.equals(PropertyManager.get("task.application"))) {
				continue;
			}
			if (!firstClusterProperties.contains(property)) {
				distance += Math.pow(1, n);
				n++;
			}
		}
		
		/*
		 * Вычисляет расстояние, как среднеквардратичное между весами свойств
		 * задач в кластерах. Вес свойства задачи в кластере определяется, как
		 * отношение количества задач с таким свойством к общему количеству задач
		 * в кластере.
		 */
//		
//		Map<Property, Double> metrics = new HashMap<Property, Double>();
//		TaskClusterMetrics firstTaskClusterMetrics = new TaskClusterMetrics(firstTaskCluster);
//		TaskClusterMetrics secondTaskClusterMetrics = new TaskClusterMetrics(secondTaskCluster);
//		
//		metrics.putAll(firstTaskClusterMetrics.getPropertyWeights());
//		for (Entry<Property, Double> entry : secondTaskClusterMetrics.getPropertyWeights().entrySet()) {
//			if (PropertyManager.get("task.application").equals(entry.getKey())) {
//				continue;
//			}
//			Double value = metrics.get(entry.getKey());
//			
//			if (value == null) { // no such property
//				metrics.put(entry.getKey(), entry.getValue());
//			} else { // put difference
//				value -= entry.getValue(); 
//				metrics.put(entry.getKey(), value);
//			}
//		}
//		
//		// now calculate distance
//		double distance = 0.0;
//		for (Double value : metrics.values()) {
//			distance += value * value;
//		}
		return distance; //Math.sqrt(distance);
	}
	
	public static Set<Property> getPropertySet(TaskCluster cluster) {
		Set<Property> properties = new HashSet<Property>();
		for (Task task : cluster.getTasks()) {
			properties.addAll(task.getPropertySet());
		}
		return properties;
	}
}
